package uz.rt.physics;

import uz.rt.math.Interpolator;
import uz.rt.units.Length;

import java.util.ArrayList;
import java.util.Collections;

public class TprList extends ArrayList<Tpr>
{
// -------------------------- OTHER METHODS --------------------------

    /**
     * Get a tpr value in function of the equivalent square field size and depth
     *
     * @param eqf   Equivalent square field size
     * @param depth Depth
     * @return An tpr value (uses linear interpolation between multiple tpr sets if needed
     * @see Interpolator
     */
    public double getValue(final Length eqf, final Length depth)
    {
        if (isEqfsInValid(eqf)) throw new ArithmeticException(
                "Equivalent square field size is exceeding the field size boundaries [minimum field size <= eqf <= maximum field size].");
        // make sure all units are equal
        depth.scale(eqf.getUnit());
        equaliseScales(eqf.getUnit());
        for (Tpr tpr : this)
        {
            if (tpr.getEquivalentFieldSize() == eqf) return tpr.get(depth);
        }
        Tpr a = get(0);
        Tpr b = get(size() - 1);
        for (Tpr tpr : this)
        {
            // since all units are now equal:
            if (a.getEquivalentFieldSize().getValue() < tpr.getEquivalentFieldSize().getValue() &&
                    tpr.getEquivalentFieldSize().getValue() < eqf.getValue())
                a = tpr;
            if (b.getEquivalentFieldSize().getValue() > tpr.getEquivalentFieldSize().getValue() &&
                    tpr.getEquivalentFieldSize().getValue() > eqf.getValue())
                b = tpr;
        }
        return Interpolator.linear(eqf.getValue(), a.getEquivalentFieldSize().getValue(),
                                   b.getEquivalentFieldSize().getValue(), a.get(depth), b.get(depth));
    }

    /**
     * Checks if the equivalent square fieldsize is outside the tpr dataset.
     *
     * @param eqf Equivalent square fieldsize
     * @return True if the fieldsize is out of bound and thus invalid, false if the fieldsize within range.
     */
    private boolean isEqfsInValid(final Length eqf)
    {
        equaliseScales(eqf.getUnit());
        sort();
        return eqf.getValue() < get(0).getEquivalentFieldSize().getValue() ||
                eqf.getValue() > get(size() - 1).getEquivalentFieldSize().getValue();
    }

    /**
     * Sort all Tpr classes
     */
    private void sort()
    {
        Collections.sort(this);
    }

    /**
     * Set all units of the tpr curves equal
     *
     * @param unit Length unit
     */
    protected void equaliseScales(Length.Unit unit)
    {
        for (Tpr tpr : this)
            tpr.equaliseScales(unit);
    }
}
